﻿using System;
using Gadgeteer.Interfaces.Fakes.Framework;
using System.Threading;

namespace Gadgeteer.Interfaces.Fakes
{
    /// <summary>
    /// Fake button; simulate a button in memory.
    /// </summary>
    public class FakeButton : DelayedAction, IButton
    {
        private static int unNamedButtons = 0;
        private DateTime pressedUntil = DateTime.MinValue;
        private bool isPressed;

        /// <summary>
        /// Create a fake button.
        /// </summary>
        public FakeButton()
            : this("Fake " + ++unNamedButtons)
        {
        }

        /// <summary>
        /// Create a fake button and assing the Thread name with <paramref name="name"/>.
        /// </summary>
        public FakeButton(string name)
            : base(name)
        {
            isPressed = false;
        }

        /// <summary>
        /// Is the button currently pressed?
        /// </summary>
        public bool IsPressed
        {
            get { return isPressed; }
        }

        private static readonly TimeSpan defaultPressLength = new TimeSpan(0, 0, 0, 0, 50);

        /// <summary>
        /// Press the button for 50 miliseconds.
        /// A human press never directly releases.
        /// </summary>
        public void Press()
        {
            Press(defaultPressLength);
        }

        /// <summary>
        /// Press the button during the given timespan.
        /// A human press never directly releases.
        /// </summary>
        /// <param name="pressFor">Timespan to press the button for.</param>
        public void Press(TimeSpan pressFor)
        {
            ExecuteAsDelayed(() =>
            {
                OnButtonPressed();
                isPressed = true;

                Thread.Sleep((int)pressFor.Milliseconds);

                isPressed = false;
                OnButtonReleased();
            },
                new TimeSpan(0, 0, 0, 0, 10)
            );
        }

        #region Press/Release events
        private void OnButtonPressed()
        {
            var ev = ButtonPressed;
            if (ev != null)
                ev(this, ButtonState.Pressed);
        }

        /// <summary>
        /// <see cref="IButton.ButtonPressed"/>
        /// </summary>
        public event ButtonEventHandler ButtonPressed;

        private void OnButtonReleased()
        {
            var ev = ButtonReleased;
            if (ev != null)
                ev(this, ButtonState.Released);
        }

        /// <summary>
        /// <see cref="IButton.ButtonReleased"/>
        /// </summary>
        public event ButtonEventHandler ButtonReleased;
        #endregion
    }
}
